﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using LowLevelGraphics.Filter;
using LowLevelGraphics.Drawing;

using Direction = LowLevelGraphics.Filter.Contours.Direction;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// ExperimentalContourExtraction
    /// </summary>
    public class ExperimentalContourExtraction : BaseImageFilter
    {
        private Point m_ptStart = Point.Empty;
        private int m_nThreshold = 7;
        private bool m_bFindFirstPoint = true;

        /// <summary>
        /// Gets or sets point to start
        /// </summary>
        public Point Start
        {
            get { return m_ptStart; }
            set { m_ptStart = value; }
        }

        /// <summary>
        /// Gets or sets threshold
        /// </summary>
        public int Threshold
        {
            get { return m_nThreshold; }
            set { m_nThreshold = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public ExperimentalContourExtraction()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_ExperimentalContourExtraction"></param>
        internal ExperimentalContourExtraction(ExperimentalContourExtraction _ExperimentalContourExtraction)
        {
            m_ptStart = _ExperimentalContourExtraction.m_ptStart;
            m_nThreshold = _ExperimentalContourExtraction.m_nThreshold;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmapCloned = (UnsafeBitmap)_bitmap.Clone();
            int xRel = m_ptStart.X;
            int yRel = m_ptStart.Y;

            int x = 0;
            int y = 0;
            int m_nWindowSize = 3;

            int xRelLast = 0;
            int yRelLast = 0;
            //until break found
            Color color1 = bitmapCloned.GetPixel(xRel, yRel);
            int nDistanceMax = 0;

            int xTemp = 0;
            int yTemp = 0;

            int nWidth = _bitmap.Width;
            int nHeight = _bitmap.Height;

            Direction direction = Direction.N;

            xRel = m_nWindowSize; 
            yRel = m_nWindowSize;

            while (true)
            {
                for (y = -m_nWindowSize / 2; y < m_nWindowSize / 2; y++)
                {
                    for (x = -m_nWindowSize / 2; x < m_nWindowSize / 2; x++)
                    {
                        //use function here.... calculate gradient change....
                        xTemp = xRel + x;
                        yTemp = yRel + y;

                        if (xTemp > nWidth - 1) break;
                        if (xTemp < 0) break;
                        if (yTemp > nHeight - 1) break;
                        if (yTemp < 0) break;

                        Color color2 = bitmapCloned.GetPixel(xTemp, yTemp);
                        int nDistance = ColorFunctions.DistanceSquared(color1, color2);
                        if (nDistance > nDistanceMax)
                        {
                            xRelLast = xTemp;
                            yRelLast = yTemp;
                            nDistanceMax = nDistance;
                        }
                    }
                    direction = DetermineDirection(x, y, m_nWindowSize, xRelLast, yRelLast);
                }

                //breaks                    
                if (nDistanceMax < m_nThreshold) break;

                //Change direction parameters.
                UnsafeGraphics.IncreaseDirectionDependant(ref xRel, ref yRel, direction);

                /*if (xRel > nWidth - 1) break;
                if (xRel < 0) break;
                if (yRel > nHeight - 1) break;
                if (yRel < 0) break;*/

                if (xRel > nWidth - 1) continue;
                if (xRel < 0) continue;
                if (yRel > nHeight - 1) continue;
                if (yRel < 0) continue;

                _bitmap.SetPixel(xRel, yRel, Color.Red);
            }
            return _bitmap;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="_nWindowSize"></param>
        /// <param name="_xRelLast"></param>
        /// <param name="_yRelLast"></param>
        private Direction DetermineDirection(int x, int y, int _nWindowSize, int _xRelLast, int _yRelLast)
        {
            //Get directions
            Direction direction = Direction.N;
            if (_xRelLast == x && _yRelLast == y)
            {
                direction = Direction.N;
            }
            else if (_xRelLast == x && _yRelLast == _nWindowSize)
            {
                direction = Direction.S;
            }
            else if (_xRelLast == x && _yRelLast == y)
            {
                direction = Direction.W;
            }
            else if (_xRelLast == x && _yRelLast == y)
            {
                direction = Direction.E;
            }
            else if (_xRelLast == x && _yRelLast == y)
            {
                direction = Direction.NE;
            }
            else if (_xRelLast == x && _yRelLast == y)
            {
                direction = Direction.SE;
            }
            else if (_xRelLast == x && _yRelLast == y)
            {
                direction = Direction.SW;
            }
            else if (_xRelLast == x && _yRelLast == y)
            {
                direction = Direction.NW;
            }
            return direction;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new ExperimentalContourExtraction(this);
        }
    }
}
